// Test script for briefing service functionality
const { Ollama } = require('ollama');
const fs = require('fs-extra');
const path = require('path');

// Test configuration
const TEST_CONFIG = {
  ollamaHost: 'http://localhost:11434',
  testDocsDir: './example-docs',
  briefingsDir: './.cb-document-helper/briefings'
};

// Mock DocumentInfo type for testing
function createDocumentInfo(filePath, content) {
  const matter = require('gray-matter');
  const parsed = matter(content);
  
  return {
    filePath,
    content,
    frontMatter: parsed.data,
    lastModified: new Date()
  };
}

// Test the Ollama connection and available models
async function testOllamaConnection() {
  console.log('🔧 Testing Ollama connection...');
  
  try {
    const ollama = new Ollama({ host: TEST_CONFIG.ollamaHost });
    
    // List available models
    const models = await ollama.list();
    console.log('✅ Ollama connected successfully');
    console.log('Available models:');
    models.models.forEach(model => {
      console.log(`  - ${model.name} (${(model.size / 1024 / 1024 / 1024).toFixed(2)} GB)`);
    });
    
    return models.models;
  } catch (error) {
    console.error('❌ Failed to connect to Ollama:', error.message);
    return null;
  }
}

// Test briefing generation with different models
async function testBriefingGeneration(models) {
  console.log('\n📝 Testing briefing generation...');
  
  if (!models || models.length === 0) {
    console.error('❌ No models available for testing');
    return;
  }
  
  // Find suitable model for testing
  const suitableModels = models.filter(m => 
    m.name.includes('qwen') || 
    m.name.includes('llama') || 
    m.name.includes('chatglm') ||
    m.name.includes('baichuan')
  );
  
  if (suitableModels.length === 0) {
    console.log('⚠️  No Chinese-capable models found, using first available model');
    var testModel = models[0].name;
  } else {
    var testModel = suitableModels[0].name;
  }
  
  console.log(`Using model: ${testModel}`);
  
  // Test with Chinese document
  const testDoc = `---
title: "Python机器学习指南"
category: "技术文档"
tags: ["机器学习", "Python", "数据科学"]
author: "张三"
date: "2024-01-01"
---

# Python机器学习入门指南

## 概述
机器学习是人工智能的一个重要分支，通过算法让计算机能够从数据中学习模式，并做出预测或决策。

## 主要内容

### 1. 环境准备
- 安装Python 3.8+
- 安装必要的库：numpy, pandas, scikit-learn
- 配置Jupyter Notebook开发环境

### 2. 数据预处理
数据预处理是机器学习项目的关键步骤：
- 数据清洗：处理缺失值、异常值
- 特征工程：特征选择、特征变换
- 数据标准化：归一化、标准化

### 3. 算法选择
常用的机器学习算法包括：
- 监督学习：线性回归、决策树、随机森林、SVM
- 无监督学习：K-means聚类、层次聚类
- 深度学习：神经网络、CNN、RNN

### 4. 模型评估
- 交叉验证
- 性能指标：准确率、召回率、F1分数
- 过拟合与欠拟合的诊断

## 实战项目
本指南包含三个实战项目：
1. 房价预测（回归问题）
2. 图像分类（分类问题）
3. 客户聚类（聚类问题）

## 总结
通过本指南的学习，读者将掌握Python机器学习的基础知识和实践技能，能够独立完成简单的机器学习项目。
`;

  try {
    const ollama = new Ollama({ host: TEST_CONFIG.ollamaHost });
    const documentInfo = createDocumentInfo('/test/python-ml-guide.md', testDoc);
    
    // Create prompt similar to BriefingService
    const prompt = `请为以下markdown文档写一个简洁的中文摘要，要求：
1. 摘要长度不超过500字
2. 突出文档的主要内容和关键信息
3. 关注文档的内容，而非结构。比如，如果此文档描述了一个角色，你应摘要：<角色名>，男，性格<性格>，是一个<角色描述>，而不是：此文档包含角色性别、性格、描述方面的信息
4. 如果有frontmatter元数据，请在摘要中提及相关信息

文档路径: ${documentInfo.filePath}

Frontmatter metadata:
${JSON.stringify(documentInfo.frontMatter, null, 2)}

文档内容:
${documentInfo.content}

请生成摘要:`;

    console.log('📤 Sending request to Ollama...');
    const response = await ollama.generate({
      model: testModel,
      prompt,
      options: {
        temperature: 0.3,
        top_p: 0.9,
        top_k: 40,
      },
    });

    const briefing = response.response.trim();
    console.log('✅ Briefing generated successfully');
    console.log('📄 Generated briefing:');
    console.log('─'.repeat(80));
    console.log(briefing);
    console.log('─'.repeat(80));
    console.log(`📊 Briefing length: ${briefing.length} characters`);
    
    return briefing;
  } catch (error) {
    console.error('❌ Failed to generate briefing:', error.message);
    return null;
  }
}

// Test briefing storage and retrieval
async function testBriefingStorage(briefing) {
  console.log('\n💾 Testing briefing storage...');
  
  if (!briefing) {
    console.log('⚠️  No briefing to store');
    return;
  }
  
  try {
    // Ensure briefings directory exists
    await fs.ensureDir(TEST_CONFIG.briefingsDir);
    
    // Create test briefing data
    const testFilePath = '/test/python-ml-guide.md';
    const briefingData = {
      filePath: testFilePath,
      briefing: briefing,
      lastUpdated: new Date(),
      fileModified: new Date()
    };
    
    // Create hash for filename (simple version)
    function hashString(str) {
      let hash = 0;
      for (let i = 0; i < str.length; i++) {
        const char = str.charCodeAt(i);
        hash = ((hash << 5) - hash) + char;
        hash = hash & hash;
      }
      return Math.abs(hash).toString(36);
    }
    
    const hash = hashString(testFilePath);
    const briefingFile = path.join(TEST_CONFIG.briefingsDir, `${hash}.json`);
    
    // Save briefing
    await fs.writeJson(briefingFile, briefingData, { spaces: 2 });
    console.log('✅ Briefing saved successfully');
    console.log(`📁 Saved to: ${briefingFile}`);
    
    // Test retrieval
    const retrievedData = await fs.readJson(briefingFile);
    console.log('✅ Briefing retrieved successfully');
    console.log('📊 Retrieved data summary:');
    console.log(`  - File path: ${retrievedData.filePath}`);
    console.log(`  - Briefing length: ${retrievedData.briefing.length} characters`);
    console.log(`  - Last updated: ${retrievedData.lastUpdated}`);
    
    return briefingFile;
  } catch (error) {
    console.error('❌ Failed to store/retrieve briefing:', error.message);
    return null;
  }
}

// Test with real documents if they exist
async function testWithRealDocuments() {
  console.log('\n📚 Testing with real documents...');
  
  try {
    if (!(await fs.pathExists(TEST_CONFIG.testDocsDir))) {
      console.log('⚠️  No example-docs directory found');
      return;
    }
    
    const files = await fs.readdir(TEST_CONFIG.testDocsDir);
    const mdFiles = files.filter(f => f.endsWith('.md'));
    
    if (mdFiles.length === 0) {
      console.log('⚠️  No markdown files found in example-docs');
      return;
    }
    
    console.log(`📄 Found ${mdFiles.length} markdown files:`);
    mdFiles.forEach(file => console.log(`  - ${file}`));
    
    // Test with first Chinese document
    const chineseFiles = mdFiles.filter(f => f.includes('chinese'));
    if (chineseFiles.length > 0) {
      const testFile = chineseFiles[0];
      const filePath = path.join(TEST_CONFIG.testDocsDir, testFile);
      const content = await fs.readFile(filePath, 'utf-8');
      
      console.log(`\n📖 Testing with document: ${testFile}`);
      console.log(`📊 Document length: ${content.length} characters`);
      
      const documentInfo = createDocumentInfo(filePath, content);
      console.log(`🏷️  Frontmatter keys: ${Object.keys(documentInfo.frontMatter).join(', ')}`);
      
      return documentInfo;
    } else {
      console.log('⚠️  No Chinese documents found for testing');
      return null;
    }
  } catch (error) {
    console.error('❌ Failed to test with real documents:', error.message);
    return null;
  }
}

// Test briefing service performance
async function testBriefingPerformance(models) {
  console.log('\n⚡ Testing briefing service performance...');
  
  if (!models || models.length === 0) {
    console.log('⚠️  No models available for performance testing');
    return;
  }
  
  const testModel = models.find(m => m.name.includes('qwen')) || models[0];
  
  const shortDoc = `---
title: "测试文档"
---
# 简短测试
这是一个简短的测试文档。`;

  const longDoc = `---
title: "长文档测试"
category: "测试"
---
# 长文档测试

${'这是一个很长的段落。'.repeat(100)}

## 第一部分
${'内容内容内容。'.repeat(50)}

## 第二部分
${'更多内容。'.repeat(50)}

## 结论
${'总结内容。'.repeat(30)}`;

  try {
    const ollama = new Ollama({ host: TEST_CONFIG.ollamaHost });
    
    // Test short document
    console.log('📄 Testing short document...');
    const startTime1 = Date.now();
    const shortDocInfo = createDocumentInfo('/test/short.md', shortDoc);
    const shortPrompt = `请为以下markdown文档写一个简洁的中文摘要，要求：
1. 摘要长度不超过500字
2. 突出文档的主要内容和关键信息

文档内容:
${shortDocInfo.content}

请生成摘要:`;
    
    const shortResponse = await ollama.generate({
      model: testModel.name,
      prompt: shortPrompt,
      options: { temperature: 0.3 }
    });
    const shortTime = Date.now() - startTime1;
    
    console.log(`✅ Short document processed in ${shortTime}ms`);
    console.log(`📊 Input: ${shortDoc.length} chars, Output: ${shortResponse.response.length} chars`);
    
    // Test long document
    console.log('📄 Testing long document...');
    const startTime2 = Date.now();
    const longDocInfo = createDocumentInfo('/test/long.md', longDoc);
    const longPrompt = `请为以下markdown文档写一个简洁的中文摘要，要求：
1. 摘要长度不超过500字
2. 突出文档的主要内容和关键信息

文档内容:
${longDocInfo.content}

请生成摘要:`;
    
    const longResponse = await ollama.generate({
      model: testModel.name,
      prompt: longPrompt,
      options: { temperature: 0.3 }
    });
    const longTime = Date.now() - startTime2;
    
    console.log(`✅ Long document processed in ${longTime}ms`);
    console.log(`📊 Input: ${longDoc.length} chars, Output: ${longResponse.response.length} chars`);
    
    console.log(`\n⚡ Performance summary:`);
    console.log(`  - Short doc: ${shortTime}ms for ${shortDoc.length} chars`);
    console.log(`  - Long doc: ${longTime}ms for ${longDoc.length} chars`);
    console.log(`  - Speed ratio: ${(longTime / shortTime).toFixed(2)}x`);
    
  } catch (error) {
    console.error('❌ Performance test failed:', error.message);
  }
}

// Main test function
async function main() {
  console.log('🚀 Starting BriefingService comprehensive test\n');
  
  // Test 1: Ollama connection
  const models = await testOllamaConnection();
  if (!models) {
    console.log('\n❌ Cannot proceed without Ollama connection');
    return;
  }
  
  // Test 2: Briefing generation
  const briefing = await testBriefingGeneration(models);
  
  // Test 3: Storage and retrieval
  const briefingFile = await testBriefingStorage(briefing);
  
  // Test 4: Real documents
  const realDoc = await testWithRealDocuments();
  
  // Test 5: Performance testing
  await testBriefingPerformance(models);
  
  // Cleanup
  if (briefingFile) {
    console.log('\n🧹 Cleaning up test files...');
    try {
      await fs.remove(briefingFile);
      console.log('✅ Test files cleaned up');
    } catch (error) {
      console.log('⚠️  Failed to clean up test files:', error.message);
    }
  }
  
  console.log('\n🎉 BriefingService test completed!');
}

// Run the test
main().catch(error => {
  console.error('💥 Test failed with error:', error);
  process.exit(1);
});
